﻿using System;
using System.Collections.Generic;
using NetAccess.Client;
using GalaSoft.MvvmLight.Messaging;

namespace SimpleChat.Network
{
    class Client : ClientLayer
    {
        private IMessenger MessengerInstance { get; set; }

        private readonly string _appId;
        private readonly int _serviceTCPPort;
        private readonly string _serverPassword;
        private readonly string _username;


        public Client(IMessenger messengerInstance, string username, string serverPassword = "")
        {
            _appId = Properties.Settings.Default.ApplicationIdentifier;
            _serviceTCPPort = Properties.Settings.Default.ServiceTCPPort;
            _serverPassword = serverPassword;
            _username = username;

            MessengerInstance = messengerInstance;
        }

        public static void BeginDiscovery(Action<ServiceData> discoveryCallback, Action endCallback)
        {
            BeginDiscovery(
                new ClientConfiguration(Properties.Settings.Default.ApplicationIdentifier, System.Net.IPAddress.Any, 0, 0) { ServiceDiscoveryPort = Properties.Settings.Default.DiscoveryPort },
                false, 
                discoveryCallback, 
                endCallback);
        }

        public void Connect(string ip) {
            Connect(new ClientConfiguration(_appId, ip, _serviceTCPPort, 0));
        }

        protected override object[] PrepareHandShake()
        {
            return new object[]
                       {
                           _serverPassword,       // Send server password
                           _username      // Send username
                       };
        }

        protected override void OnConnectComplete(NetAccess.Common.ConnectionResult result, string message = null, Exception exception = null)
        {
            switch(result)
            {
                case NetAccess.Common.ConnectionResult.Accept:
                    MessengerInstance.Send(new ChatContentMessage(String.Format("Successfully connected to the server"), ChatContentMessage.MessageType.System));
                    break;
                case NetAccess.Common.ConnectionResult.TimeOut:
                    MessengerInstance.Send(new ChatContentMessage(String.Format("Connexion timeout"), ChatContentMessage.MessageType.System));
                    break;
            }
        }

        protected override void OnConnexionLost(NetAccess.Message.NetworkMessage datas = null)
        {
            MessengerInstance.Send(new ChatContentMessage(String.Format("Connexion lost with the server"), ChatContentMessage.MessageType.System));
            MessengerInstance.Send(new UserListMessage(UserListMessage.MessageType.Clear, 0, ""));
        }

        public override void DataReceived(NetAccess.Message.NetworkMessage message)
        {
            var mType = (Contracts.NetworkMessageType)message.MessageIdentifier;

            switch(mType)
            {
                case Contracts.NetworkMessageType.ChatMessage:
                    var textMessage = message.MessageData[0] != null ? (string)message.MessageData[0] : "";
                    MessengerInstance.Send(new ChatContentMessage(textMessage, ChatContentMessage.MessageType.Chat));
                    break;
                case Contracts.NetworkMessageType.UserList:
                    foreach (var user in (IEnumerable<KeyValuePair<int, String>>)message.MessageData[0])
                    {
                        MessengerInstance.Send(new UserListMessage(UserListMessage.MessageType.Add, user.Key, user.Value));   
                    }
                    break;
                case Contracts.NetworkMessageType.UserConnect:
                    MessengerInstance.Send(new UserListMessage(UserListMessage.MessageType.Add, (int)message.MessageData[0], (string)message.MessageData[1]));   
                    break;
                case Contracts.NetworkMessageType.UserDisconnect:
                    MessengerInstance.Send(new UserListMessage(UserListMessage.MessageType.Remove, (int)message.MessageData[0], ""));
                    break;
            }
        }

        public void SendChat(string message)
        {
            Send(new NetAccess.Message.NetworkMessage(Contracts.NetworkMessageType.ChatMessage, message));
        }
    }
}
